﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
using System.Windows.Forms;

namespace ClientApplication
{
    class Presenter
    {
        public Login _logIn;
        public Judge1 _judge1;
        public IAdmin1 _admin1;
        public IAdmin2 _admin2;
        public IAdmin3 _admin3;
        public IAdmin4 _admin4;
        public IAdmin5 _admin5;
        public IClient _client;
        public int loggedIn = 0;
        
        public Presenter(Login view1, Judge1 view2, IClient client, IAdmin1 admin1, IAdmin2 admin2, IAdmin3 admin3, IAdmin4 admin4, IAdmin5 admin5, ref int loggedIn)
        {
            this._logIn = view1;
            this._judge1 = view2;
            this._client = client;
            
            this._admin1 = admin1;
            this._admin2 = admin2;
            this._admin3 = admin3;
            this._admin4 = admin4;
            this._admin5 = admin5;

            this._logIn.ConnectClicked += Connect;
            
            this._client.RefreshConnectedJudges += GiveConnectedJudgesToForm;
            this._client.GiveNewContestantMessageToAdminForm += PrintNewContestantMessageInForm;
            this._client.GiveJudgingMessageToJudgeForm += PrintJudgingMessageInForm;
            this._client.GiveActiveJumpToAdminForm += PrintActiveJumpInCompetition;
            this._client.GiveMessageToAdminForm += PrintMessageInAdminLog;
            this._client.GiveGeneralMessageToJudgeForm += PrintGeneralMessageInForm;
            this._client.LoggedIn += SwitchView;
            this._client.GiveFinishedContestsToAdminForm += ShowFinishedContestsInAdminForm;
            this._client.GiveContestPacketToAdminForm += ShowContestResult;
            this._client.GiveActiveContestPacketToAdminForm += UpdateActiveContestPacket;
            this._client.UpdateJudgeTextBoxGreen += UpdateJudgeTextBoxGreen;
            this._client.UpdateJudgeTextBoxRed += UpdateJudgeTextBoxRed;
            this._client.UpdateJudgeTextBoxWhite += UpdateJudgeTextBoxWhite;
            this._client.ResetEndedCompetition += ResetAdminForm;
            this._judge1.ScoreButtonClicked += SendScore;

            this._admin1.SendJumpCode += SendJumpCodeToServer;
            this._admin1.SetupRules += RulesToClient; 
            this._admin1.AddContestant += OpenAddContestantForm1;
            this._admin1.UpdateContestant += SendContestantsToServer;
            this._admin1.SendJudges += SendChosenJudgesToServer;
            this._admin1.FinishedContestsRequest += RefreshContestlistsRequest;
            this._admin1.ViewContestRequest += SendViewContestRequest;
            this._admin1.ViewContestantDetails += ShowContestantResultDetails;

            this._admin2.ReadFromFile += ReadContestantsFromXMLFile;
            this._admin2.AddManual += OpenAddContestantForm2;

            this._admin3.CopyContestants += CopyContestants;

            loggedIn = this.loggedIn;
        }

        private void ResetAdminForm(object sender, EventArgs e)
        {
            _admin1.ResetCompetition();
        }

        private void UpdateActiveContestPacket(object sender, ContestPacket contestPacket)
        {
            _admin1.UpdateActiveContestPacket(contestPacket);
        }

        private void ShowContestantResultDetails(object sender, int contestantId)
        {
            _admin5.PrintContestantDetails(_admin1.GetTempContestPacket(), contestantId);
            _admin5.ShowDialog();
        }

        private void ShowContestResult(object sender, ContestPacket contestPacket)
        {
            _admin1.ShowContestResult(contestPacket);
        }

        private void SendViewContestRequest(object sender, Guid guid)
        {
            _client.SendViewContestRequest(guid);
        }

        private void ShowFinishedContestsInAdminForm(object sender, List<string> FinishedContests)
        {
            _admin1.ShowRefreshedContestList(FinishedContests);
        }

        private void RefreshContestlistsRequest(object sender, EventArgs e)
        {
            _client.SendFinishedContestsRequest();
        }

        private void SendChosenJudgesToServer(object sender, ChosenJudgeEventArgs e)
        {
            _client.SendChosenJudgesToServer(e);
        }

        public void Connect(object sender, LoginEventArgs e)
        {
            Thread handleLoginThread = new Thread(() => this._client.Login(e.GetId, e.GetPassword, e.GetServerIP, 5000));
            handleLoginThread.IsBackground = true;
            handleLoginThread.Start();
            handleLoginThread.Join();
            if(loggedIn != 0)
                _logIn.Close();
        }

        public void SendScore(object sender, string message)
        {
            Thread sendScore = new Thread(() => _client.SendingScore(message));
            sendScore.IsBackground = true;
            sendScore.Start();
        }

        public void SwitchView(object sender, ResponseEventArgs e)
        {
            if (e.GetResponseType == 1)
                loggedIn = 1;
            else if (e.GetResponseType == 2)
                loggedIn = 2;
            else
                loggedIn = 0;
            if (loggedIn == 1)
            {
                Thread Listen = new Thread(() => _client.GettingAndHandlingMessagesAdmin());
                Listen.IsBackground = true;
                Listen.Start();
            }
            else if (loggedIn == 2)
            {
                Thread Listen = new Thread(() => _client.GettingAndHandlingMessagesJudge());
                Listen.IsBackground = true;
                Listen.Start();
            }
        }

        public void OpenAddContestantForm1(object sender, EventArgs e)
        {
            _admin2.ShowDialog();
        }

        public void OpenAddContestantForm2(object sender, EventArgs e)
        {
            _admin2.Close();
            _admin3.SetGender(_admin1.GetGenderComboBoxValue());
            _admin3.ShowDialog();
        }

        public void CopyContestants(object sender, CopyContestantsEventArgs e)
        {
            this._admin1.AddContestantFromAdmin3(e.contestant);
        }

        public void SendContestantsToServer(object sender, CopyContestantsEventArgs e)
        {
            _client.SendContestantsToServer(e);
        }

        public void PrintJudgingMessageInForm(object sender, JudgingMessageEventArgs e)
        {
            _judge1.HandleJudgingMessage(e.GetContestantNumber, e.GetJumpCode, e.GetJumpNr);
        }

        public void PrintNewContestantMessageInForm(object sender, string message)
        {
            _admin1.HandleContestantMessage(message);
        }

        public void PrintGeneralMessageInForm(object sender, string message)
        {
            _judge1.HandleGeneralMessage(message);
        }

        public void PrintMessageInAdminLog(object sender, string message)
        {
            _admin1.HandleLogMessage(message);
        }

        public void RulesToClient(object sender, SetupRulesArgs e)
        {
            _client.SendRulesAsXML(e);
        }

        public void PrintActiveJumpInCompetition(object sender, string ID, string name, string nationality, string jumpNumber)
        {
            _admin1.HandleNewJumpFromServer(ID, name, nationality, jumpNumber);
        }

        public void ReadContestantsFromXMLFile(object sender, ReadFromFileEventArgs e)
        {
            ContestantList cList = new ContestantList();

            cList = cList.ReadContestantsFromXMLFile(e.filename);

            this._admin1.AddContestantFromAdmin2(cList);
        }

        public void GiveConnectedJudgesToForm(object sender, List<JudgeSerializable> jList)
        {
            _admin1.UpdateJudges(jList);
        }

        public void SendJumpCodeToServer(object sender, string jumpCode)
        {
            _client.SendJumpCode(jumpCode);
        }

        public void SendJudgeMissingReply(object sender, ChosenJudgeEventArgs e)
        { 
        }

        public void UpdateJudgeTextBoxGreen(object sender, string message)
        {
            this._admin1.JudgeTextBoxUpdateGreen(message);
        }

        private void UpdateJudgeTextBoxRed(object sender, string judge)
        {
                this._admin1.JudgeTextBoxUpdateRed(judge);
        }

        private void UpdateJudgeTextBoxWhite(object sender, string judge)
        {
            this._admin1.JudgeTextBoxUpdateWhite(judge);
        }

    }
}
